﻿using com.yoozoo.gta.Gameplay.PVE;
using com.yoozoo.gta.Gameplay.PVE.Editor;
using Gameplay.PVE;
using LogSystem;
using NpcFramework;
using NpcFramework.Traffic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Yoozoo.Core.Extensions.CSharp;
using Yoozoo.Gameplay.City;
using Yoozoo.Gameplay.Liberty;
using Yoozoo.Gameplay.SceneSeparate;

[CustomEditor(typeof (SceneSeparateManager))]
public class ExampleEditor : Editor
{
    private SceneSeparateManager m_Target;
    private GgameSceneConfig mapData;
    private Editor cacheEditor;

    void OnEnable()
    {
        m_Target = target as SceneSeparateManager;
    }

    private bool OneKeyDone(string rootName, string mapConfigName, bool lod1, bool renderSetting)
    {

        if (m_Target.transform.childCount != 0)
        {
            EditorUtility.DisplayDialog("Error", "当前物体下有子物体,请删除~", "ok");
            return false;
        }

        if (SceneConfigExporter.CheckPrefabs(true))
        {
            if (!string.IsNullOrEmpty(mapConfigName))
            {
                if (EditorUtility.DisplayDialog("警告", "是否导出场景数据?", "确认", "取消"))
                {
                    if (SceneConfigExporter.Export(rootName, mapConfigName, renderSetting, sceneRootPath))
                    {
                        var mapPath = sceneRootPath + mapConfigName + ".asset";
                        mapData = AssetDatabase.LoadAssetAtPath<GgameSceneConfig>(mapPath);
                        if (mapData != null)
                        {
                            // 添加区域与收集地图数据
                            SceneMapCreator.CreateMap(mapConfigName, m_Target);
                            CollectMapData(mapConfigName, true);

                            if (!renderSetting)
                            {
                                AssetDatabase.DeleteAsset(mapPath);
                            }
                            else
                            {
                                mapData.PrefabDatas = null;
                                mapData.PrefabPaths = null;
                                EditorUtility.SetDirty(mapData);
                                AssetDatabase.SaveAssetIfDirty(mapData);
                            }
                            return true;
                        }
                        else
                        {
                            EditorUtility.DisplayDialog("错误", "请先执行收集场景数据", "关闭");
                        }
                    }

                    EditorUtility.ClearProgressBar();
                }
            }
            else
            {
                EditorUtility.DisplayDialog("Error", "请填写正确的地图配置文件名", "OK");
                return false;
            }
        }

        return false;
    }

    private bool ExportBirthData(string mapConfigName)
    {
        if (!string.IsNullOrEmpty(mapConfigName))
        {
            if (EditorUtility.DisplayDialog("警告", "是否导出场景数据?", "确认", "取消"))
            {
                CollectBirthData(mapConfigName);
                return true;
            }
        }
        else
        {
            EditorUtility.DisplayDialog("Error", "请填写正确的地图配置文件名", "OK");
            return false;
        }

        return false;
    }

    void ExportSceneData(string mapConfigName,int sceneType)
    {
        string rootName = "[Root]/";
        bool lod1 = false;
        bool renderSetting = false;
        

        switch (sceneType)
        {
            case 1:
                rootName += "Street";
                renderSetting = true;
                break;
            case 2:
                UnityEngine.Debug.LogErrorFormat("该类型已废弃");
                break;
            case 3:
                UnityEngine.Debug.LogErrorFormat("该类型已废弃");
                break;
            case 4:
                UnityEngine.Debug.LogErrorFormat("该类型已废弃");
                break;
            case 5:
                UnityEngine.Debug.LogErrorFormat("该类型已废弃");
                break;
            case 6:
                UnityEngine.Debug.LogErrorFormat("该类型已废弃");
                break;
            case 7:
                UnityEngine.Debug.LogErrorFormat("该类型已废弃");
                break;
            
            case 8:
                // 打靶数据
                rootName += "Shooting";
                renderSetting = true;
                break;
            case 9:
                UnityEngine.Debug.LogErrorFormat("该类型已废弃");
                break;
            
            case 12:
                // 出生点数据
                mapConfigName += "_birth";
                rootName += "Shooting";
                lod1 = false;
                renderSetting = false;
                ExportBirthData(mapConfigName);
                return;
        }

        if (OneKeyDone(rootName, mapConfigName, lod1,renderSetting))
        {
            if (m_Target.transform.childCount > 0)
            {
                for (int j = m_Target.transform.childCount - 1; j >= 0; j--)
                {
                    GameObject.DestroyImmediate(m_Target.transform.GetChild(j).gameObject);
                }
            }
        }
    }


    private void ExportCity(string mapConfigName, int l)
    {
        SceneConfigExporter.onStartExport = () =>
        {

        };

        SceneConfigExporter.additionalAction = (data, o) =>
        {
            data.additionalInfo = new List<string>();
            // 对应房间ID
            data.additionalInfo.Add("");
            if (o.transform)
            {
                RoomIDDefiner idDefiner = o.transform.GetComponent<RoomIDDefiner>();
                if (idDefiner)
                {
                    data.additionalInfo[0] = idDefiner.roomID.ToString();
                }
            }

            // 对应产业的ID
            data.additionalInfo.Add("");
            if (o.transform.parent)
            {
                CityIndustryContainer industryContainer =
                    o.transform.parent.GetComponent<CityIndustryContainer>();
                if (industryContainer)
                {
                    data.additionalInfo[1] = industryContainer.industryId.ToString();
                }
            }

            // 空气墙对应的迷雾ID
            data.additionalInfo.Add("");
            data.additionalInfo.Add("");
            AirWallDefiner wallDefiner = o.transform.GetComponent<AirWallDefiner>();
            LibertyFogDefiner fogDefiner = null;
            if (o.transform.parent)
            {
                fogDefiner = o.transform.parent.GetComponent<LibertyFogDefiner>();
            }

            if (fogDefiner != null)
            {
                data.additionalInfo[2] = fogDefiner.FogAreaId.ToString();
            }

            if (wallDefiner != null)
            {
                data.additionalInfo[3] = wallDefiner.transform.name.Trim();
            }

        };

        ExportSceneData(mapConfigName, l);

        SceneConfigExporter.additionalAction = null;
        SceneConfigExporter.onStartExport = null;

        EditorUtility.ClearProgressBar();
    }

    public override void OnInspectorGUI()
    {
        var mapConfigName = m_Target.mapConfigName;
        if (m_Target.showEditor)
        {
            if (GUILayout.Button("导出街道数据", GUILayout.Height(40)))
            {
                ExportCity(mapConfigName,1);
            }

            if (GUILayout.Button("导出打靶设置", GUILayout.Height(40)))
            {
                ExportCity(mapConfigName,8);
            }


            if (GUILayout.Button("自动生成动态行人、车辆生成点", GUILayout.Height(40)))
            {
                AutoCreateBirthPoint();
            }

            if (GUILayout.Button("导出出生点数据", GUILayout.Height(40)))
            {
                ExportCity(mapConfigName,12);
            }

            if (GUILayout.Button("导出内城数据配置", GUILayout.Height(30)))
            {
                ExportCityDataCfg(mapConfigName);
                EditorUtility.ClearProgressBar();
            }

            if (GUILayout.Button("导出配置点数据", GUILayout.Height(30)))
            {
                if (!ExportCityPointData(false))
                {

                }
            }

            if (GUILayout.Button("导出蓝图点数据", GUILayout.Height(30)))
            {
                ExportBluePrintPointData();
            }

            if (GUILayout.Button("重算RenderQueue", GUILayout.Height(30)))
            {
                SceneConfigExporter.RecalculateMaterialRenderQueue();
            }

            if (GUILayout.Button("批量设置TextureStreaming", GUILayout.Height(30)))
            {
                SceneConfigExporter.ReimportAllTextureWithTextureStreamingOpen();
            }

            //if (GUILayout.Button("设置SceneObjectBinder", GUILayout.Height(30)))
            //{
            //    CheckSceneObjectBinder();
            //}

            //if (GUILayout.Button("检查config", GUILayout.Height(30)))
            //{
            //    StatsSceneData();
            //}

            SceneConfigExporter.UseBlockBake = GUILayout.Toggle(SceneConfigExporter.UseBlockBake, "使用分块烘焙");
            SceneConfigExporter.IsExportMaterial = GUILayout.Toggle(SceneConfigExporter.IsExportMaterial, "是否导出材质");
            SceneConfigExporter.IsCombineMesh = GUILayout.Toggle(SceneConfigExporter.IsCombineMesh, "是否合并网格");
            SceneConfigExporter.IsRecalculateMaterialRenderQueue = GUILayout.Toggle(SceneConfigExporter.IsRecalculateMaterialRenderQueue, "是否自动重算RenderQueue");
            SceneConfigExporter.GroundObj = EditorGUILayout.ObjectField("地面", SceneConfigExporter.GroundObj
                , typeof(GameObject), true) as GameObject;
            GUILayout.Label("  -地面物件上所有的材质的RenderQueue会被排到最后");

            GUILayout.Space(10);

            // if (GUILayout.Button("一键导出<挂机>场景配置", GUILayout.Height(40)))
            // {
            //     SceneConfigExporter.onStartExport = () => { };
            //
            //     SceneConfigExporter.additionalAction = (data, o) => { };
            //     if (OneKeyDone(mapConfigName))
            //     {
            //         EditorUtility.DisplayDialog("Success", "导出挂机数据成功 ^_^ ", "OK");
            //     }
            //
            //     SceneConfigExporter.additionalAction = null;
            //     SceneConfigExporter.onStartExport = null;
            // }

            GUILayout.Space(20);

            if (GUILayout.Button("检测Prefab规范", GUILayout.Height(35)))
            {
                SceneConfigExporter.CheckPrefabs();
            }

            // if (GUILayout.Button("收集场景数据", GUILayout.Height(35)))
            // {
            //     if (!string.IsNullOrEmpty(mapConfigName))
            //     {
            //
            //         if (EditorUtility.DisplayDialog("警告", "是否导出场景数据?", "确认", "取消"))
            //         {
            //             if (SceneConfigExporter.Export(mapConfigName))
            //             {
            //                 EditorUtility.DisplayDialog("", "收集场景数据成功", "关闭");
            //             }
            //
            //             EditorUtility.ClearProgressBar();
            //         }
            //     }
            //     else
            //     {
            //         EditorUtility.DisplayDialog("Error", "请填写正确的地图配置文件名", "OK");
            //     }
            // }
            //
            //
            // if (GUILayout.Button("添加区域", GUILayout.Height(35)))
            // {
            //     var mapPath = "Assets/ResourcesAssets/Pve/Scene/" + mapConfigName + ".asset";
            //     mapData = AssetDatabase.LoadAssetAtPath<GgameSceneConfig>(mapPath);
            //     if (mapData != null)
            //     {
            //         SceneTest.CreateMap(mapConfigName, m_Target);
            //     }
            //     else
            //     {
            //         EditorUtility.DisplayDialog("错误", "请先执行收集场景数据", "关闭");
            //     }
            // }
            //
            //
            // if (GUILayout.Button("生成地图配置", GUILayout.Height(35)))
            // {
            //     CollectMapData(mapConfigName);
            // }
            //
            // if (GUILayout.Button("还原场景", GUILayout.Height(35)))
            // {
            //     if (m_Target.transform.childCount != 0)
            //     {
            //         EditorUtility.DisplayDialog("Error", "请先删除该物体下的子物体", "关闭");
            //         return;
            //     }
            //
            //     if (m_Target.sceneData == null)
            //     {
            //         EditorUtility.DisplayDialog("Error", "请选择场景配置文件", "关闭");
            //         return;
            //     }
            //
            //     if (EditorUtility.DisplayDialog("警告", "确定要根据旧地图配置还原场景吗？如果有新编辑的地图配置将会丢失！", "确定", "取消"))
            //     {
            //         revertAllChildFromAsset();
            //     }
            // }
        }

        base.OnInspectorGUI();
        GUILayout.Space(20);

        if (m_Target.sceneData)
        {
            if (cacheEditor == null)
            {
                cacheEditor = Editor.CreateEditor(m_Target.sceneData);
            }
            cacheEditor.OnInspectorGUI();
        }
        
    }

    /// <summary>
    /// 统计场景数据，为数据简化做准备
    /// </summary>
    private static void StatsSceneData()
    {
#if false
        string configPath = "Assets/ResourcesAssets/Pve/Scene/citySceneConfig_streetLod0_separateData.asset";
        var config = AssetDatabase.LoadAssetAtPath<SceneSeparateManagerData>(configPath);
        if (config)
        {
            var map = new Dictionary<string, List<SceneObjectDisplay>>();

            for (var i = 0; i < config.loadObjects.Count; i++)
            {
                var sceneObjectDisplay = config.loadObjects[i];
                sceneObjectDisplay.Check(i, false, SceneObjType.Dynamic, map);
            }

            Debug.Log(LogModule.City, $"检查完毕, loadedObjects: {config.loadObjects.Count}");

            for (var i = 0; i < config.staticObjects.Count; i++)
            {
                var sceneObjectDisplay = config.staticObjects[i];
                sceneObjectDisplay.Check(i, true, SceneObjType.Static, map);
            }

            Debug.Log(LogModule.City, $"检查完毕, staticObjects: {config.staticObjects.Count}");
        }
#endif
    }

    private bool ExportCityDataCfg(string mapConfigName,bool oneKey = false)
    {
        var roomDataList = FindObjectsOfType<RoomData>().ToList();
        Dictionary<int, RoomData> rMap = new Dictionary<int, RoomData>();

        // 规范检查
        foreach (var roomData in roomDataList)
        {
            if (roomData.rID == 0)
            {
                EditorUtility.DisplayDialog("Error", "导出房间数据失败，房间ID为0,请查看错误Log", "Ok");
                Debug.LogError(LogModule.CityRoom,"导出房间数据失败，房间ID为0",roomData);
                return false;
            }

            if (roomData.jumpPoint == null)
            {
                EditorUtility.DisplayDialog("Error", "导出房间数据失败，房间没有设定边界会跳转点", "Ok");
                Debug.LogError(LogModule.CityRoom,"导出房间数据失败，房间没有设定边界会跳转点",roomData);
                return false;
            }

            if (roomData.hudPoints!=null)
            {
                
            }
            
            if (rMap.ContainsKey(roomData.rID))
            {
                EditorUtility.DisplayDialog("Error", "导出房间数据失败，存在重复ID的房间,请查看错误Log", "Ok");
                Debug.LogError(LogModule.CityRoom,$"导出房间数据失败，存在重复ID的房间，ID：{roomData.rID}",roomData);
                return false;
            }
            
            if (roomData.transform.parent == null || 
                roomData.transform.parent.name != "DataRoot")
            {
                EditorUtility.DisplayDialog("Error", "RoomData位置不对,请查看错误Log", "Ok");
                Debug.LogError(LogModule.CityRoom,$"RoomData位置不对，请放在DataRoot节点下，ID：{roomData.rID}",roomData);
                return false;
            }
        }

        string filePath = Application.dataPath + "/ResourcesAssets/City/Preload/Prefabs/RoomData";
        if (Directory.Exists(filePath))
        {
            DirectoryInfo direction = new DirectoryInfo(filePath);
            FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);
            for (int i = 0; i < files.Length; ++i)
            {
                UnityEditor.FileUtil.DeleteFileOrDirectory(filePath + "/" + files[i].Name);
                //AssetDatabase.DeleteAsset(filePath + "/" + files[i].Name);
                AssetDatabase.Refresh();
            }
        }
        else
        {
            Directory.CreateDirectory(filePath);
        }

        List<string> roomResPath = new List<string>();
        float c = 0;
        foreach (var roomData in roomDataList)
        {
            c+=1.0f;

            rMap[roomData.rID] = roomData;
            roomData.transform.name = "RoomData" + roomData.rID.ToString();
            roomData.position = roomData.transform.position;
            roomData.eulerAngles = CityGlobalValue.RoomDataAngle;
            roomData.scale = Vector3.one; // roomData.transform.localScale;

            // 清空预览状态的hud
            if (roomData.hudPoints!=null)
            {
                foreach (var hudPoint in roomData.hudPoints)
                {
                    if (hudPoint!=null && hudPoint.hPos!=null)
                    {
                        int ct = hudPoint.hPos.transform.childCount;
                        if (ct > 0)
                        {
                            for (int i = 0; i < ct; i++)
                            {
                                GameObject.DestroyImmediate(hudPoint.hPos.GetChild(i).gameObject);
                            }
                        }

                        //hudPoint.hPos.localScale = CityGlobalValue.HudDefaultScale;
                        hudPoint.hPos.localEulerAngles = CityGlobalValue.HudDefaultAngle;
                    }
                }
            }
            
            EditorUtility.DisplayProgressBar("导出房间数据","房间："+ roomData.transform.name,c/roomDataList.Count);
            
            bool saveSuccess;
            string path = "Assets/ResourcesAssets/City/RoomData/" + roomData.transform.name + ".prefab";
            roomResPath.Add(path);
            // 防止unity保存prefab变体
            if (PrefabUtility.IsAnyPrefabInstanceRoot(roomData.gameObject))
            {
                PrefabUtility.UnpackPrefabInstance(roomData.gameObject, PrefabUnpackMode.Completely,
                    InteractionMode.UserAction);
            }
            PrefabUtility.SaveAsPrefabAssetAndConnect(roomData.gameObject, path, InteractionMode.UserAction,out saveSuccess);
            PrefabUtility.UnpackPrefabInstance(roomData.gameObject, PrefabUnpackMode.Completely,
                InteractionMode.UserAction);
        }

        // 导出配置文件
        string configPath = "Assets/ResourcesAssets/City/Config/roomDataConfig.asset";
        var roomDataConfig = AssetDatabase.LoadAssetAtPath<ScriptableObject>(configPath) as RoomDataConfig;
        if (!roomDataConfig)
        {
            roomDataConfig = ScriptableObject.CreateInstance<RoomDataConfig>();
            AssetDatabase.CreateAsset(roomDataConfig,configPath);
        }

        roomDataConfig.roomResPathArray = new List<string>();
        roomDataConfig.roomResPathArray.AddRange(roomResPath);
        
        // 导出相机初始位置与旋转
        GameObject cam = GameObject.Find("CityCamera");
        if (cam)
        {
            string cameraPath = "Assets/ResourcesAssets/City/Preload/Prefabs/CityCamera.prefab";
            PrefabUtility.SaveAsPrefabAssetAndConnect(cam, cameraPath, InteractionMode.UserAction,out var saveSuccess);
            roomDataConfig.cameraPos = cam.transform.position;
            roomDataConfig.cameraRot = cam.transform.eulerAngles;
        }
        // 导出RenderScene设置
        GameObject renderScene = GameObject.Find("CityScene");
        if (renderScene)
        {
            string renderScenePath = "Assets/ResourcesAssets/City/Preload/Prefabs/CityScene.prefab";
            PrefabUtility.SaveAsPrefabAssetAndConnect(renderScene, renderScenePath, InteractionMode.UserAction,out var saveSuccess);
        }
        
        // 导出CityManager设置
        GameObject cityManager = GameObject.Find("CityManager");
        if (cityManager)
        {
            string cityManagerPath = "Assets/ResourcesAssets/City/Prefabs/CityManager.prefab";
            PrefabUtility.SaveAsPrefabAssetAndConnect(cityManager, cityManagerPath, InteractionMode.UserAction,out var saveSuccess);
        }
        
        // 导出内城点数据
        if (!ExportCityPointData(oneKey))
        {
            return false;
        }
        
        EditorUtility.SetDirty(roomDataConfig);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();
        
        if (!oneKey)
        {
            EditorUtility.DisplayDialog("Success", "导出内城配置数据成功 ^_^ ", "Ok");
        }

        return true;
    }

    // private string CollectLod0Data()
    // {
    //     var lod0Points = FindObjectsOfType<CityPoint_Lod0>();
    //     var dict = new Dictionary<int, CityPoint_Lod0>(lod0Points.Length);
    //     var sb = new StringBuilder();
    //     var pass = true;
    //     sb.AppendLine("--代码自动生成，不能手动修改！！！");
    //     
    //     sb.AppendLine("---@class CityPoint_Lod0");
    //     sb.AppendLine("---@field type number");
    //     sb.AppendLine("---@field pos Vector3");
    //     sb.AppendLine("---@field radius number");
    //
    //     sb.AppendLine();
    //     sb.AppendLine("return {");
    //     for (int i = 0; i < lod0Points.Length; i++)
    //     {
    //         var p = lod0Points[i];
    //         if (p.id <= 0)
    //         {
    //             pass = false;
    //             break;   
    //         }
    //
    //         if (dict.ContainsKey(p.id))
    //         {
    //             pass = false;
    //             break;   
    //         }
    //
    //         dict.Add(p.id, p);
    //         
    //         sb.AppendLine("    [" + p.id + "] = {");
    //
    //         sb.AppendLine($"          type = {(int) p.pointType},");
    //
    //         var pos = p.transform.position;
    //         sb.AppendLine($"          pos = Vector3.New({pos.x}, {pos.y}, {pos.z}),");
    //
    //         sb.AppendLine($"          radius = {p.radius},");
    //
    //         sb.AppendLine("    },");
    //     }
    //     
    //     sb.Append("}");
    //     return pass ? sb.ToString() : string.Empty;
    // }

    private bool ExportCityPointData(bool oneKey)
    {
        try
        {
            // 检测ID重复
            var cityPoints = FindObjectsOfType<CityPointComponent>().ToList();
            Dictionary<int, CityPointComponent> cityPointMap = new Dictionary<int, CityPointComponent>();
            foreach (var cityPoint in cityPoints)
            {
                if (cityPoint.id <= 0)
                {
                    EditorUtility.DisplayDialog("Error", "点ID必须大于0，请查看日志", "OK");
                    Debug.LogError(LogModule.CityRoom,"点ID必须大于0",cityPoint.gameObject);
                    return false;
                }
                if (cityPointMap.ContainsKey(cityPoint.id))
                {
                    EditorUtility.DisplayDialog("Error", "ID重复，请查看日志", "OK");
                    Debug.LogError(LogModule.CityRoom,$"ID重复:{cityPoint.id}",cityPointMap[cityPoint.id].gameObject);
                    Debug.LogError(LogModule.CityRoom,$"ID重复:{cityPoint.id}",cityPoint.gameObject);
                    return false;
                }

                cityPointMap[cityPoint.id] = cityPoint;
            }
            
            cityPoints.Sort((a, b) =>
            {
                return a.id - b.id;
            });
            
            string pointDataPath =  Application.dataPath + "/../Lua/modules/city/config/CityPointData.lua";
            if (File.Exists(pointDataPath))
            {
                File.Delete(pointDataPath);
                AssetDatabase.Refresh();
            }

            FileStream fs = new FileStream(pointDataPath, FileMode.Create, FileAccess.Write);
            using (StreamWriter writer = new StreamWriter(fs))
            {
                writer.WriteLine("--代码自动生成，不能手动修改！！！");
                writer.WriteLine();
                writer.WriteLine("local CityPointData = {");

                foreach (var cityPoint in cityPoints)
                {
                    var pos = cityPoint.transform.position;
                    writer.WriteLine($"     [{cityPoint.id}] = ");
                    writer.WriteLine("     {");
                    writer.WriteLine($"          type = {(int)cityPoint.pointType},");
                    writer.WriteLine($"          pos = Vector3.New({pos.x},{pos.y},{pos.z}),");
                    writer.WriteLine("     },");
                }
                
                writer.WriteLine("}");
                writer.WriteLine("return CityPointData");
                writer.Flush();
                writer.Close();
                fs.Close();
            }

            AssetDatabase.Refresh();
        }
        catch (Exception e)
        {
            return false;
        }

        if (!oneKey)
        {
            EditorUtility.DisplayDialog("成功", "导出内城点数据成功","OK");
        }
        return true;
    }

    private void ExportBluePrintPointData()
    {
        var rootGO = GameObject.Find("BlueprintPointRoot");
        if (rootGO == null)
        {
            EditorUtility.DisplayDialog("错误", "BlueprintRoot 不存在", "OK");
            return;
        }

        var root = rootGO.transform;
        var exportObj = new BluePrintPoints(128);

        var stack = new Stack<Transform>();
        for (int i = 0; i < root.transform.childCount; i++)
        {
            var ch = root.transform.GetChild(i);
            for (int j = 0; j < ch.transform.childCount; j++)
            {
                stack.Push(ch.transform.GetChild(j));
            }
        }

        var nameRecord = new Dictionary<string, bool>();
        while (stack.Count > 0)
        {
            var t = stack.Pop();
            if (t != root)
            {
                var key = t.name;
                if (nameRecord.ContainsKey(key))
                {
                    EditorUtility.DisplayDialog("错误", "存在名为" + key + "的同名节点", "OK");
                    break;
                }
                
                exportObj.Add(t);
                nameRecord.Add(key, true);
            }
            
        }

        var savePath = "Assets/ResourcesAssets/Config/Blueprint/bluePrintPointData.json";
        FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write);
        using (StreamWriter writer = new StreamWriter(fs))
        {
            writer.Write(JsonUtility.ToJson(exportObj));
            writer.Flush();
            writer.Close();
            fs.Close();
        }
            
        AssetDatabase.Refresh();
        EditorUtility.DisplayDialog("成功", "导出蓝图位置旋转信息", "OK");
    }

    private void CollectBirthData(string mapConfigName)
    {
        if (!string.IsNullOrEmpty(mapConfigName))
        {
            Undo.RecordObject(target, "PickChilds");
            var mapDataPath = sceneRootPath + mapConfigName + "_separateData.asset";
            var oldMapConfig = AssetDatabase.LoadAssetAtPath<SceneSeparateManagerData>(mapDataPath);

            bool generate = false;
            if (oldMapConfig != null)
            {
                if (EditorUtility.DisplayDialog("警告", "已经存在数据，是否覆盖？", "确定", "取消"))
                {
                    generate = true;
                }
            }
            else
            {
                generate = true;
            }

            if (generate)
            {
                var m_TargetData = ScriptableObject.CreateInstance<SceneSeparateManagerData>();

                bool success = PickChilds(m_TargetData);
                if (success)
                {
                    m_Target.sceneData = m_TargetData;
                    
                    // 路径点
                    var wayPaths = UnityEngine.Object.FindObjectsOfType(typeof(NpcWayPath));
                    m_Target.sceneData.wayPaths = new List<NpcWayPathData>();
                    for (int i = 0; i < wayPaths.Length; i++)
                    {
                        m_Target.sceneData.wayPaths.Add((wayPaths[i] as NpcWayPath).GetData());
                    }

                    // 红绿灯
                    GameObject trafficLight = GameObject.Find("TrafficLight");
                    if (trafficLight != null)
                    {
                        TrafficLight[] trafficLights = trafficLight.GetComponentsInChildren<TrafficLight>();
                        if (trafficLights != null)
                        {
                            foreach (var light in trafficLights)
                            {
                                light.OnSaved();
                            }
                        }

                        // TODO 配上场景路径
                        PrefabUtility.SaveAsPrefabAsset(trafficLight,
                            Application.dataPath + "/ResourcesAssets/Prefabs/NpcFramework/TrafficLight.prefab");
                    }

                    AssetDatabase.CreateAsset(m_TargetData, mapDataPath);
                    //删除所有子节点
                    int childCount = m_Target.transform.childCount;
                    for (int i = 0; i < childCount; i++)
                    {
                        GameObject.DestroyImmediate(m_Target.transform.GetChild(0).gameObject);
                    }

                    //从配置文件载入所有子物件
                    //revertAllChildFromAsset(true);
                    //cacheEditor = Editor.CreateEditor(m_Target.sceneData);

                    AssetDatabase.SaveAssets();

                    EditorUtility.DisplayDialog("", "导出地图配置数据成功", "关闭");
                }

            }

        }
    }

    private void CollectMapData(string mapConfigName,bool oneKey = false)
    {
        if (!string.IsNullOrEmpty(mapConfigName))
        {
            Undo.RecordObject(target, "PickChilds");
            var mapPath = sceneRootPath + mapConfigName + ".asset";
            mapData = AssetDatabase.LoadAssetAtPath<GgameSceneConfig>(mapPath);
            if (mapData != null)
            {
                var mapDataPath = sceneRootPath + mapConfigName + "_separateData.asset";
                var oldMapConfig = AssetDatabase.LoadAssetAtPath<SceneSeparateManagerData>(mapDataPath);

                bool generate = false;
                if (oldMapConfig!=null)
                {
                    if (EditorUtility.DisplayDialog("警告","已经存在数据，是否覆盖？","确定","取消"))
                    {
                        generate = true;
                    }
                }
                else
                {
                    generate = true;
                }

                if (generate)
                {
                    var m_TargetData = CreateInstance<SceneSeparateManagerData>();

                    m_TargetData.PrefabRootPath = $"{sceneRootPath}{mapConfigName}/Prefabs/";
                    bool success = PickChilds(m_TargetData);
                    if (success)
                    {
                        m_Target.sceneData = m_TargetData;
                        m_TargetData.DetectorSize = m_Target.DetectorSize;
                        m_TargetData.CameraOffset = m_Target.CameraOffset;
                        m_TargetData.DetectorOffset = m_Target.DetectorOffset;
                        //m_TargetData.mapData = mapData;

                        // 路径点
                        var wayPaths = UnityEngine.Object.FindObjectsOfType(typeof(NpcWayPath));
                        m_Target.sceneData.wayPaths = new List<NpcWayPathData>();
                        for (int i = 0; i < wayPaths.Length; i++)
                        {
                            m_Target.sceneData.wayPaths.Add((wayPaths[i] as NpcWayPath).GetData());
                        }

                        // 红绿灯
                        GameObject trafficLight = GameObject.Find("TrafficLight");
                        if (trafficLight!=null)
                        {
                            TrafficLight[] trafficLights = trafficLight.GetComponentsInChildren<TrafficLight>();
                            if (trafficLights != null)
                            {
                                foreach (var light in trafficLights)
                                {
                                    light.OnSaved();
                                }
                            }

                            // TODO 配上场景路径
                            PrefabUtility.SaveAsPrefabAsset(trafficLight,
                                Application.dataPath + "/ResourcesAssets/Prefabs/NpcFramework/TrafficLight.prefab");
                        }

                        AssetDatabase.CreateAsset(m_TargetData, mapDataPath);
                        //删除所有子节点
                        int childCount = m_Target.transform.childCount;
                        for (int i = 0; i < childCount; i++)
                        {
                            GameObject.DestroyImmediate(m_Target.transform.GetChild(0).gameObject);
                        }

                        //从配置文件载入所有子物件
                        revertAllChildFromAsset(true);
                        cacheEditor = Editor.CreateEditor(m_Target.sceneData);
                        
                        AssetDatabase.SaveAssets();

                        if (!oneKey)
                        {
                            EditorUtility.DisplayDialog("", "导出地图配置数据成功", "关闭");
                        }
                    }
                }
            }
            else
            {
                EditorUtility.DisplayDialog("错误", "请先执行收集场景数据", "关闭");
            }
           
        }
        else
        {
            EditorUtility.DisplayDialog("Error", "请填写争取的地图配置文件名", "关闭");
        }
    }
    
    private void revertAllChildFromAsset(bool export = false)
    {
        if (m_Target.sceneData._loadObjects!=null)
        {
               
            GameObject dynamicObj = new GameObject("DynamicObjs");
            dynamicObj.transform.parent = m_Target.transform;
            for (int i = 0; i < m_Target.sceneData._loadObjects.Length; i++)
            {
                var o = m_Target.sceneData._loadObjects[i];
                o.Generate(dynamicObj.transform);
            }
        }
        if (m_Target.sceneData._staticObjects!=null)
        {
            GameObject staticObj = new GameObject("StaticObjs");
            staticObj.transform.parent = m_Target.transform;
                
            for (int i = 0; i < m_Target.sceneData._staticObjects.Length; i++)
            {
                var o = m_Target.sceneData._staticObjects[i];
                o.Generate(staticObj.transform,true);
            }
        }

        if (m_Target.sceneData.npcPoints!=null)
        {
            GameObject npcPoint = GameObject.Find("NpcPoint");

            if (npcPoint)
            {
                GameObject.DestroyImmediate(npcPoint);
            }
            npcPoint = new GameObject("NpcPoint");
            npcPoint.transform.SetSiblingIndex(2);
            Dictionary<int, NpcBrithPointData> dictionary = new Dictionary<int, NpcBrithPointData>();
            if(m_Target.sceneData.allPointData != null)
            {
                foreach (var data in m_Target.sceneData.allPointData)
                {
                    dictionary.Add(data.Index, data);
                }
            }
            int index = 1000000;
            for (int i = 0; i < m_Target.sceneData.npcPoints.Count; i++)
            {
                GameObject point = new GameObject("point" + i + "  " + m_Target.sceneData.npcPoints[i].SceneObjType);
                point.transform.position = m_Target.sceneData.npcPoints[i].Position;
                point.transform.forward = m_Target.sceneData.npcPoints[i].BrithPointData.Forward;
                var bindData = point.AddComponent<ScceneDataBind>();
                bindData.Index = index;

                index++;
                bindData.ObjType = m_Target.sceneData.npcPoints[i].BrithPointData.ObjType;
                bindData.BrithPointData = m_Target.sceneData.npcPoints[i].BrithPointData;
                bindData.GroupId = m_Target.sceneData.npcPoints[i].BrithPointData.GroupId;
                bindData.TriggerSize = m_Target.sceneData.npcPoints[i].BrithPointData.TriggerSize;
                bindData.EventName = m_Target.sceneData.npcPoints[i].BrithPointData.EventName;
                bindData.IsNpcEvent = m_Target.sceneData.npcPoints[i].BrithPointData.IsNpcEvent;
                bindData.IsDeleteByView = m_Target.sceneData.npcPoints[i].BrithPointData.IsDeleteByView;
                bindData.NpcBornProbability = m_Target.sceneData.npcPoints[i].BrithPointData.NpcBornProbability;
                point.transform.SetParent(npcPoint.transform);
                if (m_Target.sceneData.npcPoints[i].BrithPointData.ChildBirthPoint!= null && m_Target.sceneData.npcPoints[i].BrithPointData.ChildBirthPoint.Length >0 )
                {
                    for (int j = 0; j < m_Target.sceneData.npcPoints[i].BrithPointData.ChildBirthPoint.Length; j++)
                    {
                        GameObject childPoint = new GameObject("childPoint" + j);
                        childPoint.transform.SetParent(point.transform);
                        int childPointDataIndex = m_Target.sceneData.npcPoints[i].BrithPointData.ChildBirthPoint[j];
                        var childPointData = dictionary[childPointDataIndex];
                        var childSceneData = childPoint.AddComponent<ScceneDataBind>();
                        childSceneData.Index = index;
                        childSceneData.ObjType = childPointData.ObjType;
                        childSceneData.BrithPointData = childPointData;
                        childPoint.transform.position = childPointData.Position;
                        childPoint.transform.forward = childPointData.Forward;
                        childSceneData.GroupId = childPointData.GroupId;
                        childSceneData.IsNpcEvent = childPointData.IsNpcEvent;
                        childSceneData.IsDeleteByView = childPointData.IsDeleteByView;
                        index++;
                    }
                }
            }
        }

        Dictionary<int,NpcWayPath> wayPathDic = new Dictionary<int, NpcWayPath>();
        
        if (m_Target.sceneData.wayPaths!=null && m_Target.sceneData.wayPaths.Count > 0)
        {
            GameObject wayRoot = GameObject.Find("NpcWayPath");
            if (wayRoot!=null)
            {
                GameObject.DestroyImmediate(wayRoot);
            }
            wayRoot = new GameObject("NpcWayPath");
            wayRoot.transform.SetSiblingIndex(1);
            
            for (int i = 0; i < m_Target.sceneData.wayPaths.Count; i++)
            {
                NpcWayPath npcWayPath = RevertPath(m_Target.sceneData.wayPaths[i]);
                wayPathDic.Add(npcWayPath.WayID,npcWayPath);
            }
        }

        // 红绿灯        
        GameObject trafficLight = GameObject.Find("TrafficLight");
        if (!export)
        {
            if (trafficLight!=null)
            {
                GameObject.DestroyImmediate(trafficLight);
            }
            
            trafficLight = GameObject.Instantiate(AssetDatabase.LoadAssetAtPath<GameObject>("Assets/ResourcesAssets/Prefabs/NpcFramework/TrafficLight.prefab"));

            if (trafficLight)
            {
                trafficLight.transform.name = "TrafficLight";
                trafficLight.transform.SetSiblingIndex(3);

                TrafficLight[] trafficLights = trafficLight.GetComponentsInChildren<TrafficLight>();

                if (trafficLights!=null)
                {
                    foreach (var light in trafficLights)
                    {
                        light.OnSaved();
                        
                        foreach (var pointMap in light.waitPointMaps)
                        {
                            NpcWayPoint wayPoint = wayPathDic[pointMap.WayPathID].WayPoints[pointMap.PointIndex];
                            pointMap.WayPoint = wayPoint;
                            wayPoint.TrafficLight = light;
                        }
                        
                        foreach (var pointMap in light.innerPointMaps)
                        {
                            NpcWayPoint wayPoint = wayPathDic[pointMap.WayPathID].WayPoints[pointMap.PointIndex];
                            pointMap.WayPoint = wayPoint;
                        }
                    }
                }
           
            }
        }
        else
        {
            if (trafficLight != null)
            {
                TrafficLight[] trafficLights = trafficLight.GetComponentsInChildren<TrafficLight>();

                if (trafficLights != null)
                {
                    foreach (var light in trafficLights)
                    {
                        light.OnSaved();

                        foreach (var pointMap in light.waitPointMaps)
                        {
                            NpcWayPoint wayPoint = wayPathDic[pointMap.WayPathID].WayPoints[pointMap.PointIndex];
                            pointMap.WayPoint = wayPoint;
                            wayPoint.TrafficLight = light;
                        }

                        foreach (var pointMap in light.innerPointMaps)
                        {
                            NpcWayPoint wayPoint = wayPathDic[pointMap.WayPathID].WayPoints[pointMap.PointIndex];
                            pointMap.WayPoint = wayPoint;
                        }
                    }
                }
            }
        }

       
    }
    
    public NpcWayPath RevertPath(NpcWayPathData pathData)
    {
        GameObject wayRoot = GameObject.Find("NpcWayPath");
        Transform pathObj = new GameObject("Path" + pathData.WayID).transform;
        pathObj.transform.parent = wayRoot.transform;

        NpcWayPath npcWayPath = pathObj.gameObject.AddComponent<NpcWayPath>();
        npcWayPath.IsLoop = pathData.IsLoop;
        npcWayPath.WayID = pathData.WayID;
        npcWayPath.HaveWidth = true;
        npcWayPath.WayPathType = pathData.WayPathType;
        npcWayPath.WayPoints = new List<NpcWayPoint>();
        
        for (int i = 0; i < pathData.WayPoints.Count; i++)
        {
            Transform point = new GameObject(i.ToString()).transform;
            point.parent = pathObj.transform;

            NpcWayPoint npcWayPoint = point.gameObject.AddComponent<NpcWayPoint>();
            npcWayPoint.WayPath = npcWayPath;
            
            var data = pathData.WayPoints[i];
            
            npcWayPoint.width = data.Width;
            npcWayPoint.Index = data.Index;
            npcWayPoint.transform.position = data.Position;
            npcWayPoint.transform.forward = data.Forward;
            npcWayPoint.transform.right = data.Right;
            npcWayPoint.IsGenerateCar = data.IsGenerateCar;
            npcWayPoint.IsGenerateNpc = data.IsGenerateNpc;
            npcWayPoint.BTreePath = data.BTreeName;
            npcWayPath.WayID = data.WayId;
            
            npcWayPath.WayPoints.Add(npcWayPoint);
        }

        for (int i = 0; i < pathData.WayPoints.Count; i++)
        {
            var data = pathData.WayPoints[i];
            if (data.NextIndex!=ConstValue.INVALID_INDEX)
            {
                npcWayPath.WayPoints[i].NextWayPoint = npcWayPath.WayPoints[data.NextIndex];
            }

            if (data.PrevIndex!=ConstValue.INVALID_INDEX)
            {
                npcWayPath.WayPoints[i].PrevWayPoint = npcWayPath.WayPoints[data.PrevIndex];
            }

            if (data.BranchIndex!=null)
            {
                foreach (var pointData in data.BranchIndex)
                {
                    npcWayPath.WayPoints[i].branchPoints.Add(npcWayPath.WayPoints[pointData.Index]);
                    npcWayPath.WayPoints[pointData.Index].branchRatio = pointData.Ratio;
                    npcWayPath.WayPoints[pointData.Index].branchType = pointData.BranchType;
                }
            }
        }

        return npcWayPath;
    }
    
    private bool PickChilds(SceneSeparateManagerData sceneData)
    {

        // if (m_Target.transform.childCount == 0)
        // {
        //     EditorUtility.DisplayDialog("错误", "节点下没有物体", "关闭");
        //     return false;
        // }
        List<SceneObjectDisplay> sceneObjectDisplays = new List<SceneObjectDisplay>();
        List<SceneObjectInfo> sceneObjectInfos = new List<SceneObjectInfo>();
        List<SceneNpcBirthPoint> pointList = new List<SceneNpcBirthPoint>();
        Dictionary<int,NpcBrithPointData> npcPointDataDictionary= new Dictionary<int,NpcBrithPointData>();
        var npt = GameObject.Find("NpcPoint");
        if (npt)
        {
            Transform npcPoint = npt.transform;
            PickAllBirthPoint(npcPoint, npcPointDataDictionary);
            PickBirthPointById(npcPoint, pointList, npcPointDataDictionary);
        }

        // 所有预制体的路径先存放起来，各个物件信息只保留一个序号
        sceneData.PrefabPaths = mapData.PrefabPaths.Select(x => x.Replace(sceneData.PrefabRootPath, "")).ToArray();
        prefabPathAndIndexMap = new Dictionary<string, int>();
        for (var i = 0; i < mapData.PrefabPaths.Count; i++)
        {
            prefabPathAndIndexMap[mapData.PrefabPaths[i]] = i;
        }

        // 所有MeshRenderer的光照信息也统一存放，各个物件只保留一个起始序号和长度
        meshRendererDataList = new List<MeshRendererData>();

        PickChildById(m_Target.transform, sceneObjectDisplays, sceneObjectInfos);

        foreach (var prefabPath in mapData.PrefabPaths)
        {
            var prefabContents = PrefabUtility.LoadPrefabContents(prefabPath);
            var binders = prefabContents.GetComponents<SceneObjectBinder>();
            if (binders.IsNotEmpty())
            {
                foreach (var binder in binders)
                {
                    DestroyImmediate(binder);
                }

                PrefabUtility.SaveAsPrefabAsset(prefabContents, prefabPath);
                PrefabUtility.UnloadPrefabContents(prefabContents);
            }
        }

        sceneData.MeshRendererDataList = meshRendererDataList.ToArray();

        float maxX, maxY, maxZ, minX, minY, minZ;
        maxX = maxY = maxZ = -Mathf.Infinity;
        minX = minY = minZ = Mathf.Infinity;

#if false
        if (sceneObjectDisplays.Count > 0)
        {
            List<SceneObjectDisplay> staticList = new List<SceneObjectDisplay>();
            List<SceneObjectDisplay> dynamicList = new List<SceneObjectDisplay>();
            foreach (var item in sceneObjectDisplays)
            {
                switch (item.SceneObjType)
                {
                    case SceneObjType.Static:
                        staticList.Add(item);
                        break;
                    case SceneObjType.Dynamic:
                    case SceneObjType.StaticHqOnly:
                        dynamicList.Add(item);
                        break;
                }
            }

            sceneData.loadObjects = dynamicList;
            sceneData.staticObjects = staticList;
        }
#endif

        if (sceneObjectInfos.Count > 0)
        {
            var staticList = new List<SceneObjectInfo>();
            var dynamicList = new List<SceneObjectInfo>();
            foreach (var sceneObjectInfo in sceneObjectInfos)
            {
                switch (sceneObjectInfo.SceneObjType)
                {
                    case SceneObjType.Static:
                        staticList.Add(sceneObjectInfo);
                        break;
                    case SceneObjType.Dynamic:
                    case SceneObjType.StaticHqOnly:
                        dynamicList.Add(sceneObjectInfo);
                        break;
                }
            }

            sceneData._loadObjects = dynamicList.ToArray();
            sceneData._staticObjects = staticList.ToArray();
            sceneData.allPointData = npcPointDataDictionary.Values.ToList();
        }


        //NPC生成点
        if (pointList.Count > 0)
        {
            List<SceneNpcBirthPoint> birthPointList = new List<SceneNpcBirthPoint>();
            foreach (var item in pointList)
            {
                birthPointList.Add(item);
            }
            sceneData.npcPoints = birthPointList;
        }
        

        for (int i = 0; i < sceneObjectDisplays.Count; i++)
        {
            maxX = Mathf.Max(sceneObjectDisplays[i].Bounds.max.x, maxX);
            maxY = Mathf.Max(sceneObjectDisplays[i].Bounds.max.y, maxY);
            maxZ = Mathf.Max(sceneObjectDisplays[i].Bounds.max.z, maxZ);

            minX = Mathf.Min(sceneObjectDisplays[i].Bounds.min.x, minX);
            minY = Mathf.Min(sceneObjectDisplays[i].Bounds.min.y, minY);
            minZ = Mathf.Min(sceneObjectDisplays[i].Bounds.min.z, minZ);
        }
        Vector3 size = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
        Vector3 center = new Vector3(minX + size.x/2, minY + size.y/2, minZ + size.z/2);
        sceneData.bounds = new Bounds(center, size);

        return true;
    }



    private void PickChildById(Transform transform, List<SceneObjectDisplay> sceneObjectList, List<SceneObjectInfo> sceneObjectInfos)
    {
        //是不是一个prefab
        var sceneDataBind = transform.GetComponent<ScceneDataBind>();
        if (sceneDataBind != null)
        {
            var sceneObjectDisplay = GetChildSceneObjectDisplay(transform, sceneDataBind);
            if (sceneObjectDisplay != null)
                sceneObjectList.Add(sceneObjectDisplay);

            var sceneObjectInfo = GetChildSceneObjectInfo(transform, sceneDataBind);
            if (sceneObjectInfo != null)
                sceneObjectInfos.Add(sceneObjectInfo);
        }
        else
        {
            for (int i = 0; i < transform.childCount; i++)
            {
                PickChildById(transform.GetChild(i), sceneObjectList, sceneObjectInfos);
            }
        }
    }
    private void PickAllBirthPoint(Transform transform, Dictionary<int, NpcBrithPointData> npcPointDataList)
    {
        var scceneDataBinds = transform.GetComponentsInChildren<ScceneDataBind>();
        int index = 1000000;
        foreach (var dataBind in scceneDataBinds)
        {
            dataBind.Index = index;
            dataBind.BrithPointData.Index = index;
            npcPointDataList.Add(dataBind.Index, dataBind.BrithPointData);
            index++;
        }
    }
    private void PickBirthPointById(Transform transform, List<SceneNpcBirthPoint> birthPointList, Dictionary<int, NpcBrithPointData> npcPointDataDictionary)
    {
        //是不是一个prefab
        var obj = transform.GetComponent<ScceneDataBind>();
        if (obj != null && (obj.ObjType == SceneObjType.BirthPoint || obj.ObjType == SceneObjType.BirthPointParent || obj.ObjType == SceneObjType.NpcGroup || obj.ObjType == SceneObjType.Event))
        {
            var o = GetNpcBirthPoint(transform, obj);
            o.BrithPointData.ObjType = obj.ObjType;
            o.BrithPointData.Index = obj.Index;
            o.BrithPointData.NpcBornProbability = obj.NpcBornProbability;
            o.BrithPointData.RootName = obj.name;
            var boxC = transform.GetComponent<BoxCollider>();
            if (boxC)
            {
                o.BrithPointData.checkCenter = boxC.center;
                o.BrithPointData.checkSize = boxC.size;
            }
            if (o != null)
                birthPointList.Add(o);
            if (obj.ObjType == SceneObjType.BirthPointParent)
            {
                obj.BrithPointData.ChildBirthPoint = new int[transform.childCount];
                for (int i = 0; i < obj.BrithPointData.ChildBirthPoint.Length; i++)
                {
                    var childData = transform.GetChild(i).GetComponent<ScceneDataBind>();
                    obj.BrithPointData.ChildBirthPoint[i] = childData.Index;
                    var serializeChildData = npcPointDataDictionary[childData.Index];
                    serializeChildData.Index = childData.Index;
                    serializeChildData.Position = childData.transform.position;
                    serializeChildData.Forward = childData.transform.forward;
                    serializeChildData.ObjType = childData.ObjType;
                    serializeChildData.GroupId = childData.GroupId;
                    serializeChildData.IsNpcEvent = childData.IsNpcEvent;
                    serializeChildData.EventName = childData.EventName;
                    serializeChildData.TriggerSize = childData.TriggerSize;
                    var boxCollider = childData.transform.GetComponent<BoxCollider>();
                    if (boxCollider)
                    {
                        serializeChildData.checkCenter = boxCollider.center;
                        serializeChildData.checkSize = boxCollider.size;
                    }
                }
            }
            else if (obj.ObjType == SceneObjType.NpcGroup)
            {
                o.BrithPointData.GroupId = obj.GroupId;
                o.BrithPointData.Index = obj.Index;
            }
            else if (obj.ObjType == SceneObjType.Event)
            {
                o.BrithPointData.TriggerForward = obj.BrithPointData.TriggerForward;
                o.BrithPointData.TriggerPosition = obj.BrithPointData.TriggerPosition;
                o.BrithPointData.EventName = obj.EventName;
                o.BrithPointData.TriggerSize = obj.TriggerSize;
                o.BrithPointData.IsNpcEvent = obj.IsNpcEvent;
                o.BrithPointData.Index = obj.Index;
                obj.BrithPointData.ChildBirthPoint = new int[transform.childCount];
                o.BrithPointData.EventId = obj.BrithPointData.EventId;

                for (int i = 0; i < obj.BrithPointData.ChildBirthPoint.Length; i++)
                {
                    var childData = transform.GetChild(i).GetComponent<ScceneDataBind>();
                    obj.BrithPointData.ChildBirthPoint[i] = childData.Index;
                    var serializeChildData = npcPointDataDictionary[childData.Index];
                    serializeChildData.Position = childData.transform.position;
                    serializeChildData.Forward = childData.transform.forward;
                    serializeChildData.ObjType = childData.ObjType;
                    serializeChildData.GroupId = childData.GroupId;
                    serializeChildData.IsNpcEvent = childData.IsNpcEvent;
                    serializeChildData.Index = childData.Index;
                    
                    var boxCollider = childData.transform.GetComponent<BoxCollider>();
                    if (boxCollider)
                    {
                        serializeChildData.checkCenter = boxCollider.center;
                        serializeChildData.checkSize = boxCollider.size;
                    }
                }
            }
        }
        else
        {
            for (int i = 0; i < transform.childCount; i++)
            {
                PickBirthPointById(transform.GetChild(i), birthPointList, npcPointDataDictionary);
            }
        }
    }

    private PrefabData GetChildmapDataByIndex(int index)
    {
        if (mapData)
        {
            if (index < mapData.PrefabDatas.Count)
            {
                PrefabData prefabData = mapData.PrefabDatas[index];
                prefabData.resPath = mapData.GetPrefabResPath(prefabData);
                return prefabData;
            }
            return null;
        }
        Debug.LogError("mapData is null");
        return null;
    }

    private SceneNpcBirthPoint GetNpcBirthPoint(Transform transform, ScceneDataBind sscObj)
    {
        Bounds bounds = new Bounds(transform.position, Vector3.one);
        sscObj.BrithPointData.Forward = transform.forward;
        sscObj.BrithPointData.Position = transform.position;
        SceneNpcBirthPoint birthPoint = new SceneNpcBirthPoint(
            bounds,
            sscObj.ObjType,
            transform.position,
            sscObj.BrithPointData, 
            sscObj.Index, 
            transform.name);

        return birthPoint;
    }

    private SceneObjectDisplay GetChildSceneObjectDisplay(Transform transform, ScceneDataBind sscObj)
    {
        if (sscObj.Index < 0)
        {
            Debug.LogError("Index 无效");
        }
        List<MeshRenderer> renderers = transform.gameObject.GetComponent<PrefabMeshRenderCache>().MeshRenderers;
        if (renderers == null || renderers.Count == 0)
            return null;

        Vector3 min = renderers[0].bounds.min;
        Vector3 max = renderers[0].bounds.max;
        for (int i = 1; i < renderers.Count; i++)
        {
            min = Vector3.Min(renderers[i].bounds.min, min);
            max = Vector3.Max(renderers[i].bounds.max, max);
        }
        Vector3 size = max - min;
        Bounds bounds = new Bounds(min + size / 2, size);
        if (size.x <= 0)
            size.x = 0.2f;
        if (size.y <= 0)
            size.y = 0.2f;
        if (size.z <= 0)
            size.z = 0.2f;
        bounds.size = size;

        var prefabData = GetChildmapDataByIndex(sscObj.Index);
        if (prefabData != null)
        {
            var sceneObjectDisplay = new SceneObjectDisplay(
                bounds,
                transform,
                sscObj.Index,
                prefabData,
                sscObj.IsStatic,
                sscObj.ObjType);
            return sceneObjectDisplay;
        }

        UnityEngine.Debug.LogError("配置文件中没有这个索引的数据：" + sscObj.Index);
        return null;
    }

    private SceneObjectInfo GetChildSceneObjectInfo(Transform transform, ScceneDataBind sceneDataBind)
    {
        if (sceneDataBind.Index < 0)
        {
            Debug.LogError("Index 无效");
        }
        List<MeshRenderer> renderers = transform.gameObject.GetComponent<PrefabMeshRenderCache>().MeshRenderers;
        if (renderers == null || renderers.Count == 0)
            return null;

        Vector3 min = renderers[0].bounds.min;
        Vector3 max = renderers[0].bounds.max;
        for (int i = 1; i < renderers.Count; i++)
        {
            min = Vector3.Min(renderers[i].bounds.min, min);
            max = Vector3.Max(renderers[i].bounds.max, max);
        }
        Vector3 size = max - min;
        Bounds bounds = new Bounds(min + size / 2, size);
        if (size.x <= 0)
            size.x = 0.2f;
        if (size.y <= 0)
            size.y = 0.2f;
        if (size.z <= 0)
            size.z = 0.2f;
        bounds.size = size;

        var prefabData = GetChildmapDataByIndex(sceneDataBind.Index);
        if (prefabData != null)
        {
            int startIndex = meshRendererDataList.Count;
            int count = prefabData.MeshRendererDatas.Count;
            meshRendererDataList.AddRange(prefabData.MeshRendererDatas);

            var sceneObjectInfo = new SceneObjectInfo(
                bounds,
                transform,
                sceneDataBind.Index,
                prefabPathAndIndexMap[prefabData.resPath],
                startIndex, count,
                sceneDataBind.IsStatic,
                sceneDataBind.ObjType);
            sceneObjectInfo.IsNavmeshObject = sceneDataBind.IsNavMesh;
            return sceneObjectInfo;
        }

        UnityEngine.Debug.LogError("配置文件中没有这个索引的数据：" + sceneDataBind.Index);
        return null;
    }

    // 自动生成动态行人和车辆的生成点
    private float NpcCreateDis = 100;
    private float CarCreateDis = 100;
    private void AutoCreateBirthPoint()
    {
        
        //场景中必须存在npc和汽车的路线，根据路线的距离生成点
        var npcPath = GameObject.Find("NpcPaths");
        if (npcPath == null)
        {
            EditorUtility.DisplayDialog("Error", "当前没有Npc的路线节点NpcPaths,请确认路线", "ok");
            return;
        }
        var carPath = GameObject.Find("CarSplines");
        if (carPath == null)
        {
            EditorUtility.DisplayDialog("Error", "当前没有汽车的路线节点CarSplines,请确认路线", "ok");
            return;
        }

        CreateNpcOrCarBirthPointByPath(npcPath, true);
        CreateNpcOrCarBirthPointByPath(carPath);

    }

    private void CreateNpcOrCarBirthPointByPath(GameObject checkPath, bool isNpc = false)
    {
        var npcPointTra = GameObject.Find("NpcPoint");
        if (npcPointTra == null)
        {
            npcPointTra = new GameObject("NpcPoint");
        }
        var lastCreatePoint = checkPath.transform.GetChild(0).position;
        int index = 1;
        
        for (int i = 0; i < checkPath.transform.childCount; i++)
        {
            var path = checkPath.transform.GetChild(i);
            int splineId = 0;
            if (!isNpc)
            {
                var splineData = path.GetComponent<NpcWayPath>();
                splineId = splineData.WayID;
            }
            float leftDis = 0;
            for (int j = 1; j < path.childCount; j++)
            {
                var lastPathPoint = path.GetChild(j - 1);
                var pathPoint = path.GetChild(j);
                var lastPoint = lastPathPoint.position;
                var currentPoint = pathPoint.position;
                var dis = Vector3.Distance(lastPoint, currentPoint);
                var offset = (currentPoint - lastPoint).normalized;

                var needCreateDis = NpcCreateDis;
                var createObjName = "dynamicNpc";
                var createTemplate = m_Target.NpcTemplate;
                if (!isNpc)
                {
                    needCreateDis = CarCreateDis;
                    createObjName = "car";
                    createTemplate = m_Target.CarTemplate;
                }
                    
                if (leftDis + dis >= needCreateDis)
                {
                    lastCreatePoint = lastPoint + (offset * (needCreateDis - leftDis));
                    var createObj = Instantiate(createTemplate, npcPointTra.transform);
                    var npcWayPoint = pathPoint.transform.GetComponent<NpcWayPoint>();
                    var pointIndex = npcWayPoint.Index;
                    if (isNpc)
                    {
                        createObj.name = createObjName +"_"+ index;
                    }
                    else
                    {
                        createObj.name = createObjName +"_"+ index +"_"+ splineId + "_" + pointIndex;
                    }

                    index++;
                    var data = createObj.GetComponent<ScceneDataBind>();
                    createObj.transform.position = lastCreatePoint;
                    var angles = Quaternion.FromToRotation(Vector3.forward, offset).eulerAngles;
                    createObj.transform.eulerAngles = angles;
                    data.BrithPointData.Position = lastCreatePoint;
                    data.BrithPointData.Forward = angles;
                    
                    leftDis = dis - (needCreateDis - leftDis);

                    while (leftDis >= needCreateDis)
                    {
                        lastCreatePoint += (offset * needCreateDis);
                        createObj = Instantiate(createTemplate, npcPointTra.transform);
                        if (isNpc)
                        {
                            createObj.name = createObjName +"_"+ index;
                        }
                        else
                        {
                            createObj.name = createObjName +"_"+ index+"_"+splineId;
                        }

                        index++;
                        data = createObj.GetComponent<ScceneDataBind>();
                        createObj.transform.position = lastCreatePoint;
                        data.BrithPointData.Position = lastCreatePoint;
                        leftDis -= needCreateDis;
                    }
                }
                else
                {
                    leftDis += dis;
                }
            }
            
        }
    }

    private Dictionary<string, int> prefabPathAndIndexMap;
    private List<MeshRendererData> meshRendererDataList;
    private string sceneRootPath = "Assets/ResourcesAssets/Pve/Scene/";
}
